
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author jcl_hqu
 * @date 2021/3/17 21:49
 */

public class Producer {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        // 文件映射共享内存，并设置大小为5个字节
        RandomAccessFile raf = new RandomAccessFile("D:/shareMemory.mm", "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 6);

        //清除文件内容
        for (int i = 0; i <5; i++) {
            mbb.put(i, (byte) 0);
        }

        // 初始化   index 0 1 2 用于存储数据，index 3 4 用于保证同步 3是生产者用 4是消费者用  在用时位置为byte 1
        // index 5 标识不允许使用的进程 1标识禁止生产者; -1标识禁止消费者;
        mbb.put(0, (byte) 0);
        mbb.put(1, (byte) 0);
        mbb.put(2, (byte) 0);


        int buffer;       // buffer
        int count = 0; //记录生产次数
        long startTime=0;
        while (count<100) {
            Thread.sleep(5);
            mbb.put(3,(byte) 1); mbb.put(5,(byte) -1); // 进入区
            while (mbb.get(4)==(byte) 1 && mbb.get(5)==(byte) -1) System.out.println("生产者等待");  // 如果消费者正在使用内存且生产者没有使用内存，则不进入

                             /* 临界区*/

            if (count==0){
                startTime=System.currentTimeMillis(); //获取开始时间
            }

            buffer = mbb.get(0) * 100 + mbb.get(1) * 10 + mbb.get(2); // 取得缓冲池中容量

            if (buffer < 100) {
                buffer += 1;
                count++;
                String bufferStr = String.valueOf(buffer); //int -> str
                int length = bufferStr.length();
                if (length < 3) {
                    for (int i = 0; i < 3 - length; i++){
                        bufferStr = "0" + bufferStr;
                    }
                }

                // 输出并写回
                System.out.println("生产者生产," + "当前库存" + bufferStr + "(" + count);
                mbb.put(0, (byte) (bufferStr.charAt(0) - '0'));
                mbb.put(1, (byte) (bufferStr.charAt(1) - '0'));
                mbb.put(2, (byte) (bufferStr.charAt(2) - '0'));
            }
            mbb.put(3, (byte) 0);
        }

        long endTime=System.currentTimeMillis();
        System.out.println("生产者花费时间："+(endTime-startTime));
    }
}